package com.googlecode.monitoring.dao;

import com.googlecode.monitoring.exception.StatisticDaoException;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Repository;

import java.io.*;


@Repository(value = "defaultStatisticDao")
public class DefaultStatisticDao implements StatisticDao {
    Logger log = Logger.getLogger(DefaultStatisticDao.class);
    DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern("dd.MM.yyyy");

    Resource statisticResource;

    @Autowired
    public void setStatisticResource(Resource statisticResource) {
        this.statisticResource = statisticResource;
    }

    @Override
    public void incrementTotalStateChecks(String id) {
        try {
            log.debug(statisticResource.getFile().getAbsolutePath());
            incrementValue(id, 2);
        } catch (IOException e) {
            log.error(e);
            throw new StatisticDaoException("system can't increment value for id=" + id, e);
        }
    }

    @Override
    public void incrementTotalStateDownChecks(String id) {
        try {
            incrementValue(id, 3);
        } catch (IOException e) {
            log.error(e);
            throw new StatisticDaoException("system can't increment value for id=" + id, e);
        }
    }

    private void incrementValue(String id, int numberOfValue) throws IOException {
        synchronized (statisticResource) {
            File newFile = new File(statisticResource.getFile().getAbsolutePath() + ".copy");
            BufferedReader fileReader = new BufferedReader(new FileReader(statisticResource.getFile()));
            BufferedWriter fileWriter = new BufferedWriter(new FileWriter(newFile));
            try {
                String line;
                String todayStr = dateTimeFormatter.print(new DateTime());
                boolean alredyExists = false;
                while ((line = fileReader.readLine()) != null) {
                    String[] atoms = line.split("\\;");
                    if (todayStr.equals(atoms[0]) && id.equals(atoms[1])) {
                        alredyExists = true;
                        int totalDown = Integer.parseInt(atoms[numberOfValue]);
                        totalDown++;
                        atoms[numberOfValue] = totalDown + "";
                        writeLine(fileWriter, atoms);
                    } else {
                        fileWriter.write(line);
                        fileWriter.newLine();
                    }
                }
                if (!alredyExists) {
                    String[] atoms = new String[4];
                    atoms[0] = todayStr;
                    atoms[1] = id;
                    if (numberOfValue == 2) {
                        atoms[2] = 1 + "";
                    } else {
                        atoms[2] = 0 + "";
                    }
                    if (numberOfValue == 3) {
                        atoms[3] = 1 + "";
                    } else {
                        atoms[3] = 0 + "";
                    }
                    writeLine(fileWriter, atoms);                    
                }
            } catch (Throwable e) {
                log.error(e);
                throw new StatisticDaoException("system can't increment value for id=" + id + " in file=" + newFile.getAbsolutePath(), e);
            } finally {
                fileReader.close();
                fileWriter.close();
            }
            File statResource = statisticResource.getFile();
            if (statisticResource.getFile().delete()) {
                if (!newFile.renameTo(statResource)) {
                    throw new StatisticDaoException("system can't rename file " + newFile.getAbsolutePath());
                }
            } else {
                throw new StatisticDaoException("system can't delete file " + statisticResource.getFile().getAbsolutePath());
            }
        }
    }

    @Override
    public double getPercentageUptimeForLastDays(String id, int days) throws IOException {
        DateTime dtNow = new DateTime();
        DateTime minusPeriod = dtNow.minusDays(days);
        int sumTotalChecks = 0;
        int sumTotalDown = 0;
        double percentage = 0;
        synchronized (statisticResource) {
            BufferedReader fileReader = new BufferedReader(new FileReader(statisticResource.getFile()));
            try {
                String line;
                while ((line = fileReader.readLine()) != null) {
                    String[] atoms = line.split("\\;");
                    if (id.equals(atoms[1])) {
                        DateTime dateTime = dateTimeFormatter.parseDateTime(atoms[0]);
                        if (dateTime.isAfter(minusPeriod)) {
                            sumTotalChecks += Integer.parseInt(atoms[2]);
                            sumTotalDown += Integer.parseInt(atoms[3]);
                        }
                    }
                }
            } catch (Throwable e) {
                log.error(e);
                throw new StatisticDaoException("system read stat value for id=" + id + " in file=" + statisticResource.getFile(), e);
            } finally {
                fileReader.close();
            }
        }
        if (sumTotalChecks > 0 && sumTotalDown > 0) {
            percentage = sumTotalDown * 100 / sumTotalChecks;
        }
        return percentage;
    }

    private void writeLine(BufferedWriter fileWriter, String[] atoms) throws IOException {
        StringBuffer lineToWrite = new StringBuffer();
        for (String s : atoms) {
            lineToWrite.append(s);
            lineToWrite.append(";");
        }
        fileWriter.write(lineToWrite.toString());
        fileWriter.newLine();
    }
}
